package org.richin.net.util;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.InetAddress;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLDecoder;
import java.net.URLEncoder;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;


import org.richin.file.util.FileUtils;
import org.richin.io.util.UtilException;
import org.richin.lang.util.StringUtils;

public class URLUtils {
	private static final Log log = LogFactory.getLog(URLUtils.class);
	public static final String decode(String s) throws MalformedURLException {
		try {
			return decode(s, "8859_1");
		} catch (UnsupportedEncodingException unsupportedencodingexception) {
			throw new MalformedURLException("ISO-Latin-1 decoder unavailable");
		}
	}

	public static final String decode(String s, String s1) throws MalformedURLException, UnsupportedEncodingException {
		int i = s.length();
		byte abyte0[] = new byte[i];
		int j = 0;
		for (int k = 0; k < i; k++)
			if (s.charAt(k) == '%') {
				k++;
				try {
					abyte0[j++] = (byte) Integer.parseInt(s.substring(k, k + 2), 16);
				} catch (Exception exception) {
					throw new MalformedURLException((new StringBuilder()).append("Invalid URI encoding: ").append(s)
							.toString());
				}
				k++;
			} else {
				abyte0[j++] = (byte) s.charAt(k);
			}

		return new String(abyte0, 0, j, s1);
	}

	public static final String encode(String s, String s1) throws UnsupportedEncodingException {
		byte abyte0[] = s.getBytes(s1);
		int i = abyte0.length;
		char ac[] = new char[3 * i];
		int j = 0;
		for (int k = 0; k < i; k++)
			if (abyte0[k] >= 97 && abyte0[k] <= 122 || abyte0[k] >= 65 && abyte0[k] <= 90 || abyte0[k] >= 48
					&& abyte0[k] <= 57 || "=,+;.'-@&/$_()!~*:".indexOf(abyte0[k]) >= 0) {
				ac[j++] = (char) abyte0[k];
			} else {
				ac[j++] = '%';
				ac[j++] = Character.forDigit(15 & abyte0[k] >>> 4, 16);
				ac[j++] = Character.forDigit(15 & abyte0[k], 16);
			}

		return new String(ac, 0, j);
	}

	/** 
	 * 将 String 转换为 application/x-www-form-urlencoded MIME 格式的串 
	 * @param filepath 要转换的目标的字符串，GBK格式 
	 * @return 以UTF-8编码的字符串 
	 * @throws UnsupportedEncodingException 
	 */
	public static String URLEncoder(String filepath) {
		String result = "";
		try {
			result = URLEncoder.encode(filepath, "UTF-8");
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		return result;
	}
    /**
     * 向指定URL发送POST方法的请求
     *
     * @param url
     *            发送请求的URL
     * @param param
     *            请求参数，请求参数应该是name1=value1&name2=value2的形式。
     * @return URL所代表远程资源的响应
     */
    public static String sendPost(String url, String param) {
            PrintWriter out = null;
            BufferedReader in = null;
            String result = "";
            try {
                    URL realUrl = new URL(url);
                    // 打开和URL之间的连接
                    URLConnection conn = realUrl.openConnection();
                    // 设置通用的请求属性
                    conn.setRequestProperty("accept", "*/*");
                    conn.setRequestProperty("connection", "Keep-Alive");
                    conn.setRequestProperty("user-agent",
                                    "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)");
                    // 发送POST请求必须设置如下两行
                    conn.setDoOutput(true);
                    conn.setDoInput(true);
                    // 获取URLConnection对象对应的输出流
                    out = new PrintWriter(conn.getOutputStream());
                    // 发送请求参数
                    out.print(param);
                    // flush输出流的缓冲
                    out.flush();
                    // 定义BufferedReader输入流来读取URL的响应
                    in = new BufferedReader(
                                    new InputStreamReader(conn.getInputStream()));
                    String line;
                    while ((line = in.readLine()) != null) {
                            result += "\n" + line;
                    }
            } catch (Exception e) {
                    System.out.println("发送POST请求出现异常！" + e);
                    e.printStackTrace();
            }
            // 使用finally块来关闭输出流、输入流
            finally {
                    try {
                            if (out != null) {
                                    out.close();
                            }
                            if (in != null) {
                                    in.close();
                            }
                    } catch (IOException ex) {
                            ex.printStackTrace();
                    }
            }
            return result;
    }

	/**
	 * 将字符串路径转化为URL对象
	 * @param urlspec
	 * @param relativePrefix
	 * @return
	 * @throws MalformedURLException
	 */
    public static URL toURL(String urlspec, String relativePrefix) throws MalformedURLException {
        urlspec = urlspec.trim();
        URL url;
        try {
            url = new URL(urlspec);
            if (url.getProtocol().equals("file"))
                url = makeURLFromFilespec(url.getFile(), relativePrefix);
        }
        catch (Exception e) {
            try {
                url = makeURLFromFilespec(urlspec, relativePrefix);
            }
            catch (IOException n) {
                throw new MalformedURLException(n.toString());
            }
        }
        return url;
    }
    
    private static URL makeURLFromFilespec(String filespec, String relativePrefix) throws IOException {
        File file = new File(filespec);
        if (relativePrefix != null && !file.isAbsolute())
            file = new File(relativePrefix, filespec);
        file = file.getCanonicalFile();
        return file.toURL();
    }
	/**
	 * 根据提供的域名地址返回网页html内容
	 * @param remoteUrl
	 * @return
	 */
	public static String getWebContent(String remoteUrl) {
		StringBuffer sb = new StringBuffer();
		try {
			java.net.URL url = new java.net.URL(remoteUrl);
			BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()));
			String line;
			while ((line = in.readLine()) != null) {
				sb.append(line);
			}
			in.close();
		} catch (Exception e) {
			log.error("获取远程网址内容失败 - " + remoteUrl, e);
		}
		return sb.toString();
	}

	/**
	*
	* 根据文件url地址采集并创建到本地
	*
	* @param remoteUrl  远程文件url路径
	*
	* @param filePathAndName
	*            预创建到本地的文件的绝对路径含文件名已经扩展名
	*
	* @return
	*
	*/

	public boolean readFile(String remoteUrl, String filePath, String fileName)

	{
		boolean bea = false;

		java.net.URL urlfile = null;

		HttpURLConnection httpUrl = null;

		BufferedInputStream bis = null;

		BufferedOutputStream bos = null;

		if (fileName == null || fileName.equals("")) //如果未定义文件名则以远程文件的文件名命名
			fileName = FileUtils.getExtension(remoteUrl);

		File f = new File(filePath, fileName);

		try {

			// 连接指定的网络资源,获取网络输入流

			urlfile = new java.net.URL(remoteUrl);

			httpUrl = (HttpURLConnection) urlfile.openConnection();

			httpUrl.connect();

			bis = new BufferedInputStream(httpUrl.getInputStream());

		} catch (Exception e) {
			log.error("远程文件读取失败", e);
		}

		try {
			bos = new BufferedOutputStream(new FileOutputStream(f));
			byte[] buf = new byte[1024];
			int bufsize = 0;
			while ((bufsize = bis.read(buf, 0, buf.length)) != -1) {
				bos.write(buf, 0, bufsize);
			}
			bea = true;
			log.info(remoteUrl + " 采集成功！文件已存储至：" + filePath + fileName);

		} catch (IOException e) {
			bea = false;
			log.error(remoteUrl + "采集失败", e);

		} finally {
			try {
				bos.flush();
				bis.close();
				httpUrl.disconnect();
			} catch (Exception e) {
				log.error("关闭HTTP连接失败", e);
			}
		}
		return bea;

	}

	/**
	 * 根据提供的域名地址返回网页html内容。指定编码类型
	 * @param remoteUrl
	 * @param encoding 编码类型
	 * @return
	 */
	public static String getWebContent(String remoteUrl, String encoding) {
		StringBuffer sb = new StringBuffer();
		try {
			java.net.URL url = new java.net.URL(remoteUrl);
			BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream(), encoding));
			String line;
			while ((line = in.readLine()) != null) {
				sb.append(line);
			}
			in.close();
		} catch (Exception e) { // Report any errors that arise
			log.error("获取远程网址内容失败 - " + remoteUrl, e);
		}
		return sb.toString();
	}

	/** 
	 * 将 String 从 application/x-www-form-urlencoded MIME 格式解码为UTF8格式的字符串 
	 * @param wwwurl 要转换的目标的字符串，application/x-www-form-urlencoded MIME 格式 
	 * @return UTF8格式的字符串 
	 * @throws UnsupportedEncodingException 
	 */
	public static String URLDecoder(String wwwurl) throws UnsupportedEncodingException {
		String result = "";
		try {
			result = URLDecoder.decode(wwwurl, "UTF-8");
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		return result;
	}
	/**
	 * 通过url获取主机地址,包括端口号
	 * @param url url地址
	 * @return 
	 *   example:<br>
	 *     http://localhost/* 			-> localhost <br>
	 *     http://127.0.0.1:8080/* 		-> 127.0.0.1:8080 <br>
	 *     http://www.test.com:8080/* 	-> www.test.com:8080 <br>	
	 * @throws UtilException
	 */
	public static String getHostAddr(String url)throws UtilException{
		int flagPos=url.indexOf("://");
		if(flagPos==-1)throw new UtilException(url +" is invalid url.");			
		url=url.substring(flagPos+3);
		int virgulePos=url.indexOf('/');
		return virgulePos==-1?url:url.substring(0,virgulePos);
	}
	
	
	/**
	 * 通过url获取主机名
	 * @param url url地址
	 * @return
	 * 	 example:<br>
	 *     http://localhost/* 			-> localhost <br>
	 *     http://127.0.0.1:8080/* 		-> 127.0.0.1 <br>
	 *     http://www.test.com:8080/* 	-> www.test.com <br>
	 */
	public static String getHostName(String url){
		String hostAddr=getHostAddr(url);
		int colonPos=hostAddr.indexOf(':');
		return colonPos==-1?hostAddr:hostAddr.substring(0,colonPos);
	}
	
	/**
	 * 通过url获取主机端口号
	 * @param url url地址
	 * @return
	 * 	 example:<br>
	 *     http://localhost/* 			-> {@link StringUtil.EMPTY} <br>
	 *     http://127.0.0.1:8080/* 		-> 8080 <br>
	 *     http://www.test.com:8080/* 	-> 8080 <br>	
	 */
	public static String getHostPort(String url){
		String hostAddr=getHostAddr(url);
		int colonPos=hostAddr.indexOf(':');
		return colonPos==-1?"":hostAddr.substring(colonPos+1);
	}
	
	
	/**
	 * 判断url的主机名是否是IP地址
	 * @param url url地址
	 * @return
	 * 	 example:<br>
	 *     http://localhost/* 			-> false <br>
	 *     http://127.0.0.1:8080/* 		-> true  <br>
	 *     http://www.test.com:8080/* 	-> false <br>
	 */
	public static boolean isIp(String url){
		try{
			String hostName=getHostName(url);
			Integer.valueOf(hostName.substring(hostName.lastIndexOf('.')+1));
			return true;
		}catch(Exception e){
			return false;
		}
	}
	
	/**
	 * 通过url获取域
	 * @param url url地址
	 * @return
	 *   example:<br>
	 *     http://localhost/* 			-> localhost <br>
	 *     http://127.0.0.1:8080/* 		-> 127.0.0.1 <br>
	 *     http://www.test.com:8080/* 	-> .test.com <br>	
	 */
	public static String getDomain(String url){
		String hostName=getHostName(url);
		if(isIp(url)){
			return hostName;
		}else{
			int dotPos=hostName.indexOf('.');
			return dotPos==-1?hostName:hostName.substring(dotPos,hostName.length());
		}
	}
	
	/**
	 * 判断是否是系统外部地址
	 * @param url url地址
	 * @return 是:true 否:false
	 */
	public static boolean isExternalUrl(String url){
		return url.startsWith("http://")||url.startsWith("https://")||url.startsWith("ftp://")||url.equals("about:blank");
	}
	
	/**
	 * IP地址转化成long型数的算法
	 * @param ip
	 * @return
	 */
	public static long getIP(InetAddress ip) {  
	     byte[] b = ip.getAddress();  
	     return b[0] << 24L & 0xff000000L | b[1] << 16L & 0xff0000L  | b[2] << 8L & 0xff00 | b[3] << 0L & 0xff;  
	} 
	
	public static void main(String args[]) throws Exception{
		String url="http://bbs.blueidea.com/viewthread.php?tid=2942014";
		System.out.println(getHostAddr(url));
		System.out.println(getHostName(url));
		System.out.println(isIp(url));
		System.out.println(getDomain(url));
		System.out.println(isExternalUrl(url));
		System.out.println(getHostPort(url));
	
		String filepath = "D:\\My Documents\\我接收到的文件\\20_save.gif";
		String wwwurl = URLEncoder(filepath);
		String filepath_new = URLDecoder(wwwurl);

		System.out.println(filepath);
		System.out.println(wwwurl);
		System.out.println(StringUtils.encode("我是众人20_save.随碟附送", "UTF-8"));
		System.out.println(filepath_new);
	}

}
